﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<ctype.h>
#include<assert.h>

//memcpy 使⽤和模拟实现
//• 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
//• 这个函数在遇到 '\0' 的时候并不会停下来。
//• 如果source和destination有任何的重叠，复制的结果都是未定义的。

//int main()
//{
//	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
//	int arr2[10] = { 0 };
//	memcpy(arr2, arr1, 20);//内存拷贝
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", arr2[i]);
//	}
//	return 0;
//}

//memcpy函数拷贝结束后会返回目标空间的起始地址

//void* memcpy(void* dst, const void* src, size_t count)
//{
//	void* ret = dst;
//	assert(dst);
//	assert(src);
//	/*
//	* copy from lower addresses to higher addresses
//	*/
//	while (count--) {
//		*(char*)dst = *(char*)src;
//		dst = (char*)dst + 1;
//		src = (char*)src + 1;
//	}
//	return(ret);
//}


//memmove 使⽤和模拟实现
//• 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。
//• 如果源空间和⽬标空间出现重叠，就得使⽤memmove函数处理。

//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	memmove(arr + 2, arr, 5 * sizeof(int));
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	return 0;
//}

//memcpy函数拷贝结束后会返回目标空间的起始地址

//void* memmove(void* dst, const void* src, size_t count)
//{
//	void* ret = dst;
//	if (dst <= src || (char*)dst >= ((char*)src + count)) {
//		/*
//		* Non-Overlapping Buffers
//		* copy from lower addresses to higher addresses
//		*/
//		while (count--) {
//			*(char*)dst = *(char*)src;
//			dst = (char*)dst + 1;
//			src = (char*)src + 1;
//		}
//	}
//	else {
//		/*
//		* Overlapping Buffers
//		* copy from higher addresses to lower addresses
//		*/
//		dst = (char*)dst + count - 1;
//		src = (char*)src + count - 1;
//		while (count--) {
//			*(char*)dst = *(char*)src;
//			dst = (char*)dst - 1;
//			src = (char*)src - 1;
//		}
//	}
//	return(ret);
//}
#if 0
void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	if (dest < src)
	{
		//前-后
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//后-前
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr, arr+2, 5 * sizeof(int));
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}
#endif



//memset 函数的使⽤
//memset是⽤来设置内存的，将内存中的值以字节为单位设置成想要的内容。

//int main()
//{
//	char str[] = "hello world";
//	memset(str, 'x', 6);//以字节为单位设置的
//	printf(str);
//	return 0;
//}


//memcmp 函数的使⽤
//• ⽐较从ptr1和ptr2指针指向的位置开始，向后的num个字节

//int main()
//{
//	char buffer1[] = "DWgaOtP12df0";
//	char buffer2[] = "DWGAOTP12DF0";
//	int n;
//	n = memcmp(buffer1, buffer2, sizeof(buffer1));
//	if (n > 0)
//		printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
//	else if (n < 0)
//		printf("'%s' is less than '%s'.\n", buffer1, buffer2);
//	else
//		printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
//	return 0;
//}


//1. 整数在内存中的存储
//在讲解操作符的时候，我们就讲过了下⾯的内容：
//整数的2进制表⽰⽅法有三种，即原码、反码和补码
//三种表⽰⽅法均有符号位和数值位两部分，符号位都是⽤0表⽰“正”，⽤1表⽰“负”，⽽数值位最⾼位的⼀位是被当做符号位，剩余的都是数值位。
//正整数的原、反、补码都相同。
//负整数的三种表⽰⽅法各不相同。
//原码：直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
//反码：将原码的符号位不变，其他位依次按位取反就可以得到反码。
//补码：反码 + 1就得到补码。

//对于整形来说：数据存放内存中其实存放的是补码。
//为什么呢？
//在计算机系统中，数值⼀律⽤补码来表⽰和存储。
//原因在于，使⽤补码，可以将符号位和数值域统⼀处理；
//同时，加法和减法也可以统⼀处理（CPU只有加法器）此外，补码与原码相互转换，其运算过程是相同的，不需要额外的硬件电路。

//其实超过⼀个字节的数据在内存中存储的时候，就有存储顺序的问题，按照不同的存储顺序，我们分
//为⼤端字节序存储和⼩端字节序存储，下⾯是具体的概念：
//⼤端（存储）模式：是指数据的低位字节内容保存在内存的⾼地址处，⽽数据的⾼位字节内容，保存
//在内存的低地址处。
//⼩端（存储）模式：是指数据的低位字节内容保存在内存的低地址处，⽽数据的⾼位字节内容，保存
//在内存的⾼地址处。
//为什么会有⼤⼩端模式之分呢？
//这是因为在计算机系统中，我们是以字节为单位的，每个地址单元都对应着⼀个字节，⼀个字节为8
//bit位，但是在C语⾔中除了8bit的 char 之外，还有16bit的 short 型，32bit的 long 型（要看具体的编译器），另外，对于位数⼤于8位的处理器，例如16位或者32位的处理器，由于寄存器宽度⼤
//于⼀个字节，那么必然存在着⼀个如何将多个字节安排的问题。因此就导致了⼤端存储模式和⼩端存储模式。
//例如：⼀个 16bit 的 short 型 x ，在内存中的地址为 0x0010 ， x 的值为 0x1122 ，那么
//0x11 为⾼字节， 0x22 为低字节。对于⼤端模式，就将 0x11 放在低地址中，即 0x0010 中，
//0x22 放在⾼地址中，即 0x0011 中。⼩端模式，刚好相反。我们常⽤的 X86 结构是⼩端模式，⽽
//KEIL C51 则为⼤端模式。很多的ARM，DSP都为⼩端模式。有些ARM处理器还可以由硬件来选择是
//⼤端模式还是⼩端模式。

//请简述⼤端字节序和⼩端字节序的概念，设计⼀个⼩程序来判断当前机器的字节序。（10分）-百度笔试题
//代码1
//int check_sys()
//{
//	int i = 1;
//	return (*(char*)&i);
//}
//int main()
//{
//	int ret = check_sys();
//	if (ret == 1)
//	{
//		printf("小端\n");
//	}
//	else
//	{
//		printf("大端\n");
//	}
//	return 0;
//}

//代码2
//int check_sys()
//{
//	union
//	{
//		int i;
//		char c;
//	}un;
//	un.i = 1;
//	return un.c;
//}

//signed char 类型的取值范围是：-128-127
// unsigned char 类型的取值范围是：0-255
//int main()
//{
//	char a = -1;
//	signed char b = -1;
//	unsigned char c = -1;
//	printf("a=%d,b=%d,c=%d", a, b, c);//-1  -1  255
//	return 0;
//}

//int main()
//{
//	char a = -128;
//	printf("%u\n", a);//4294967168
//	return 0;
//}

//int main()
//{
//	char a = 128;
//	printf("%u\n", a);//4294967168
//	return 0;
//}














